﻿using ApiManage.Models.MongoMappings.Sys;
using ApiManage.Models.RequestModels;
using ApiManage.Models.ResultModels;
using ApiManage.Service.Mongo.Sys;
using ApiManage.Svc.Filter;
using Microsoft.AspNetCore.Mvc;
using MongoDB.Bson;
using Rhonin.Common.Entity.Api;
using Rhonin.Common.Entity.Enum;
using Rhonin.Common.Entity.Exception;
using Rhonin.Common.Extentions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace ApiManage.Svc.Controllers
{
    /// <inheritdoc />
    /// <summary>
    /// 授权
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    public class AuthController : BaseController
    {
        private readonly ISysUserQueryService _sysUserQueryService;
        private readonly ISysMenuQueryService _sysMenuQueryService;
        private readonly ISysColumnQueryService _sysColumnQueryService;
        private readonly ISysButtonQueryService _sysButtonQueryService;
        private readonly ISysRoleQueryService _sysRoleQueryService;
        /// <summary>
        /// 
        /// </summary>
        public AuthController(ISysUserQueryService sysUserQueryService,
            ISysMenuQueryService sysMenuQueryService,
            ISysColumnQueryService sysColumnQueryService,
            ISysButtonQueryService sysButtonQueryService,
            ISysRoleQueryService sysRoleQueryService)
        {
            _sysUserQueryService = sysUserQueryService;
            _sysMenuQueryService = sysMenuQueryService;
            _sysColumnQueryService = sysColumnQueryService;
            _sysButtonQueryService = sysButtonQueryService;
            _sysRoleQueryService = sysRoleQueryService;
        }
        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="param">请求信息</param>
        /// <returns></returns>
        [Route("Login"), HttpPost]
        public ApiResult<UserLoginResult> Login(UserLogin param)
        {
            Expression<Func<SysUser, bool>> where = o => o.Mark == 1 && o.LoginName.Equals(param.Account) && o.LoginPwd.Equals(param.Pwd);
            var user = _sysUserQueryService.Get(where);
            if (user == null)
                throw new ApiException("用户不存在或密码错误");
            var ticket = Rhonin.Common.Ticket.SetTicket(user.Id.ToString(), user.UserName, Platform.Web);
            return CreateResult(new UserLoginResult
            {
                UserName = user.UserName,
                RoleName = user.RoleName,
                Ticket = ticket
            });
        }
        /// <summary>
        /// 获取登录用户信息
        /// </summary>
        /// <returns></returns>
        [HttpGet, Route("GetLoginInfo"), CheckLogin]
        public ApiResult<SysUser> GetLoginInfo()
        {
            var user = _sysUserQueryService.Get(o => o.Id == new ObjectId(UserId));
            if (user == null)
            {
                throw new ApiException("用户信息不存在");
            }
            var role = _sysRoleQueryService.Get(o => o.Id == new ObjectId(user.RoleId));
            if (role?.RoleMenuIds == null)
            {
                throw new ApiException("该用户无权限");
            }
            var userMenuIds = new List<ObjectId>();
            var userButtonIds = new List<ObjectId>();
            var userColumnIds = new List<ObjectId>();
            role.RoleMenuIds.ForEach(o => { userMenuIds.Add(new ObjectId(o)); });
            role.RoleButtonIds.ForEach(o =>
            {
                if (!o.Contains("_button"))
                {
                    userButtonIds.Add(new ObjectId(o));
                }
            });
            role.RoleColumnIds.ForEach(o =>
            {
                if (!o.Contains("_column"))
                {
                    userColumnIds.Add(new ObjectId(o));
                }
            });
            user.UserRole = _sysMenuQueryService.GetList(o => userMenuIds.Contains(o.Id));
            user.UserButton = _sysButtonQueryService.GetList(o => userButtonIds.Contains(o.Id));
            user.UserColumn = _sysColumnQueryService.GetList(o => userColumnIds.Contains(o.Id));
            user.UserMenu = GetUserMenuTree(user.UserRole);
            return CreateResult(user);
        }

        private static List<MenuTree> GetUserMenuTree(IReadOnlyCollection<SysMenu> userMenus)
        {
            var topMenu = userMenus.Where(o => o.MenuUp.IsNullOrEmpty()).OrderBy(o => o.Sort).Select(o => new MenuTree
            {
                Id = o.Id.ToString(),
                Title = o.MenuName,
                Icon = o.MenuIcon,
                Path = o.MenuUrl
            }).ToList();
            foreach (var item in topMenu)
            {
                GetMenuChildren(item, userMenus);
            }
            return topMenu;
        }

        private static void GetMenuChildren(MenuTree menu, IEnumerable<SysMenu> allMenus)
        {
            var sysMenus = allMenus as SysMenu[] ?? allMenus.ToArray();
            var childrenMenu = sysMenus.Where(o => o.MenuUp == menu.Id).OrderBy(o => o.Sort).Select(o => new MenuTree
            {
                Id = o.Id.ToString(),
                Title = o.MenuName,
                Icon = o.MenuIcon,
                Path = o.MenuUrl
            }).ToList();
            if (childrenMenu.Count <= 0) return;
            foreach (var item in childrenMenu)
            {
                GetMenuChildren(item, sysMenus);
            }
            menu.Children = childrenMenu;
        }
    }
}